
from bf_lex import *

class LineMach:
    def __init__(self):    # 不用处理错误，直接中断+err置1
        self.rules = []

    def reg(self, state, a):
        def g(f):
            self.rules.append(((state, a), f))
        return g

    def run(self, data, debug=True):
        state = Ss()
        data += ["end"]
        for a in data:
            state = self.reduction(state, a, debug)
        assert isinstance(state, Xs)
        return state.x

    def reduction(self, state, a, debug):
        for (t1, t2), f in self.rules:
            if match(state, t1) and match(a, t2):
                if debug:
                    print("match from", state, a)
                    print( "match", repr(t1), repr(t2))
                r = f(state, a)
                if debug:
                    print("to", r)
                return r
        else:
            print("err1", state, a)
            raise Exception("无可匹配的规则")





def match(x, pattern):
    if isinstance(pattern, type):
        return isinstance(x, pattern)
    elif isinstance(pattern, list):
        flag = False
        for p2 in pattern:
            if match(x, p2):
                flag = True
                break
        return flag
    elif callable(pattern):
        return pattern(x)
    else:
        return x == pattern


class State:
    pass


class Ss(State):
    def __init__(self):
        pass

    def __repr__(self):
        return f"<Ss>"
        
    def first(self, x):
        return 


class Xs(State):
    def __init__(self, x):
        self.x = x

    def __repr__(self):
        return f"<Xs>"


class Fs(State):
    def __init__(self, last, f, k):
        self.last = last
        self.f = f
        self.k = k      # 左右结合权重

    def __repr__(self):
        return f"<Fs>"
        
    def eat(self, x): 
        return Fxs(self.last, self.f, x, self.k)
    
    @classmethod
    def from2(cls, last, op, x): 
        return Fs(last, [op.f] + [x], op.k) 



class Fxs(State):
    def __init__(self, last, f, x, k):
        self.last = last
        self.f = f
        self.x = x
        self.k = k

    def __repr__(self):
        return f"<Fxs>"
        
    def spew(self):
        return Fs(self.last, self.f, self.k), self.x


lm = LineMach()

table_op2 = {}

class Op2:
    def __init__(self, f, k, left=False):
        self.f = f
        self.k = k
        if left == False:
            self.k_tail = k
        else:
            self.k_tail = k - 0.1

def new_op2(f, k, left=False):
    table_op2[f] = Op2(f, k, left)


def ABC_Op2(x):
    if not isinstance(x, Word):
        return False
    return x.s in table_op2

table_head = {}

class Head:
    def __init__(self, f, k):
        self.f = f
        self.k = k

def new_head(f, k):
    table_head[f] = Head(f, k)

def ABC_Head(x):
    if not isinstance(x, Word):
        return False
    return x.s in table_head



@lm.reg(Ss, ABC_Head)
def f(ss, a):
    op = table_head[a.s]
    return Fs(None, [op.f], op.k)


@lm.reg(Ss, [Word, Num, String, RawTuple, RawList])
def f(ss, a):
    return Xs(a)




@lm.reg(Xs, ABC_Op2)
def f(xs, a):
    op = table_op2[a.s]
    return Fs(None, [op.f, xs.x], op.k_tail)


@lm.reg(Xs, "end")
def f(xs, a):
    return xs





@lm.reg(Fxs, ABC_Op2)
def f(fxs, a):
    op = table_op2[a.s]
    fs, x = fxs.spew()
    if fs.k < op.k: #抢夺参数
        return Fs.from2(fs, op, x)
    else:
        while fs.last is not None and fs.last.k >= op.k:
            fs, x = fs.last, fs.f + [x]
        return Fs.from2(fs.last, op, fs.f + [x])



@lm.reg(Fxs, "end")
def f(fxs, a):
    fs, x = fxs.spew()
    while fs.last is not None:
        fs, x = fxs.last, fs.f + [x]
    return Xs(fs.f + [x])


@lm.reg(Fs, ABC_Head)
def f(fs, a):
    op = table_head[a.s]
    return Fs(fs, [op.f], op.k)


@lm.reg(Fs, "end")      # 仅为break tag/ break这种语法准备
def f(fs, a):
    fs, x = fs, '...'
    while fs.last is not None:
        fs, x = fxs.last, fs.f + [x]
    return Xs(fs.f + [x])

@lm.reg(Fs, [Word, Num, String, RawTuple, RawList])
def f(fs, a):
    return fs.eat(a)




# List

@lm.reg(Xs, RawList)
def f(xs, a):
    #a = RawList([deep_tuple(lm.run(it, False)) for it in a.l])
    return Fxs(None, ["item", xs.x], a, 15)

@lm.reg(Fxs, RawList)
def f(fxs, a):
    #a = RawList([deep_tuple(lm.run(it, False)) for it in a.l])
    op = Op2('item', 15)
    fs, x = fxs.spew()
    if fs.k < op.k: #抢夺参数
        return Fs.from2(fs, op, x).eat(a)
    else:
        while fs.last is not None and fs.last.k >= op.k:
            fs, x = fs.last, fs.f + [x]
        return Fs.from2(fs.last, op, fs.f + [x]).eat(a)


# Tuple

@lm.reg(Xs, RawTuple)
def f(xs, a):
    #a = RawTuple([deep_tuple(lm.run(it, False)) for it in a.l], a.hascomma)
    return Fxs(None, ["call", xs.x], a, 15)


@lm.reg(Fxs, RawTuple)
def f(fxs, a):
    #a = RawTuple([deep_tuple(lm.run(it, False)) for it in a.l], a.hascomma)
    op = Op2('call', 15)
    fs, x = fxs.spew()
    if fs.k < op.k: #抢夺参数
        return Fs.from2(fs, op, x).eat(a)
    else:
        while fs.last is not None and fs.last.k >= op.k:
            fs, x = fs.last, fs.f + [x]
        return Fs.from2(fs.last, op, fs.f + [x]).eat(a)

"""
指数运算符：具有最高的优先级。
~、+、-：按位翻转，一元加号和减号。
*、/、%、//：乘法、除法、取模和取整除。  11
+、-：加法和减法。  10
、<<：位移运算符。9
&：位与运算符。8
^、|：位运算符。7
<=、<、>、>=：比较运算符。 6
==、!=：等于运算符。 5
赋值运算符：=、%=、/=、//=、-=、+=、*=、**=。
身份运算符：is、is not。
成员运算符：in、not in。
逻辑运算符：not、or、and
"""


# List/Tuple调用的优先级和.相同
new_op2(".", 15)
new_op2("**", 13, left=True)
new_op2("*",  11)
new_op2("/",  11)
new_op2("//",  11)
new_op2("%",  11)
new_op2("+", 10)
new_op2("-", 10)
new_op2("=<", 6)
new_op2("<", 6)
new_op2(">=", 6)
new_op2(">", 6)
new_op2("==", 5)
new_op2("!=", 5)
new_op2("-", 10)

new_op2("=", -10, left=True)
new_op2("is", -11)
new_op2("isnot", -11)
new_op2("in", -12)
new_op2("notin", -12)
new_op2("and", -13)
new_op2("or", -13)
new_op2("not", -13)

new_head("+", 12)
new_head("-", 12)



# 语法句
new_head("if", -20)
new_head("elif", -20)


# ~ new_op2("if", -20)
# ~ new_op2("then", -20, left=True)
# ~ new_op2("else", -20, left=True)

# ~ new_op2(":", -30)

# ~ new_head("if", -20)
# ~ new_op2("if", -20)
# ~ new_op2("then", -20)
# ~ new_op2("else", -20)

new_head("for", -20)
new_op2("in", -20)

# ~ new_head("case", -20)
# ~ new_op2("as", 0)


def deep_tuple(tree):       # 列表转元组
    if not isinstance(tree, list):
        return tree
    else:
        return tuple([deep_tuple(x) for x in tree])


def parseline_step1(linel: "line list"):  # 不处理注释、多行字符串，没有跨行语法，不考虑缩进
    assert isinstance(linel, list)
    r =  lm.run(linel, debug=False)
    return deep_tuple(r)



def showparse1(r):
    from tool_treeprint import tree
    def name(o):
        if isinstance(o, (tuple, list)):
            return str(o[0])
        elif isinstance(o, RawTuple):
            return "#()"
        else:
            return str(o)

    def member(o):
        if isinstance(o, (tuple, list)):
            return list(o[1:])
        elif isinstance(o, RawTuple):
            return o.l
        else:
            return []

    tree(r, name, member)


def test(s):
    doc = scan(s)
    line  = doc.l[0]
    print(line)
    r = parseline_step1(line.l)
    print(r)

    showparse1(r)




if __name__ == "__main__":
    # 基本
    # ~ test("a")
    # ~ test("1")
    # ~ test("a = 1")
    # ~ test("a = 1 + 2 * 3")
    # ~ test("1 * 2 + 3 = b")
    #test("5 = 4= 3")

    # 列表
    # ~ test("a[1]")
    # ~ test("a[1] = 1")
    # ~ test("l = a[1]")
    # ~ test("l[1] = a[1]")
    #test("l[0][1][2] = l[2]")

    # 属性运算
    # ~ test("a.1")
    # ~ test("a.x")
    # ~ test("a.x = 2")
    #test("l[0][1][2] = l[2]")
    # ~ test("a = 1 + 2 * 3")
    # ~ test("1 * 2 + 3 = b")
    # ~ test("2 * 3 **4 * b+acc")
    # ~ test("2 ** 3 **4")
    # 混合
    # ~ test("p[0] ** 2 + p[1] ** 2")
    # ~ test("p.x[0] ** 2 + p[1].x ** 2  + static()[]")
    test("p.x[0] ** 2 + p[1].x ** 2  + static().[]()")
    ## 关键字
    # ~ test("if i == 2 then 10 else 20")
    # ~ test("if i == 2 then 10 else if j == 3 then 20 else 30")
    # ~ test("if i == 2 then  if k == 4 then 40 else 50 else 20")
    # ~ test("10 if i == 2 else 20 if j == 3 else 30")
    # ~ test("1+++2---3")
    # ~ test("")
    # ~ test("print(a + 1)")

    #test("for (i, j ,k) in range(10).reversed()")

    # ~ test("for (i, j ,k) in range(10).reversed() if i > 5")
    # ~ test("case Point(x=1, y=2) as p")
    # ~ test("case Node(value=1, next=Node(value=1, next=need) as pp) as p")
    #test("4 + 1 * 2 + 5")
    #test("if 1 < 2")
    # ~ test("x.l[0] = 1")
    #test("x = y")
    #test("x")















